using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Diagnostics.Contracts;

namespace Konst3d.Efficiency
{
    public class ObservableList2<T> : IList<T>, INotifyCollectionChanged
    {
        #region INotifyCollectionChanged Implementation

        public event NotifyCollectionChangedEventHandler CollectionChanged;

        protected void NotifyCollectionChanged(NotifyCollectionChangedEventArgs args)
        {
            if (!_updateInProgress && CollectionChanged != null)
            {
                CollectionChanged(this, args);
            }
        }

        #endregion

        #region IList<T> Members

        public int IndexOf(T item)
        {
            throw new NotImplementedException();
        }

        public void Insert(int index, T item)
        {
            throw new NotImplementedException();
        }

        public void RemoveAt(int index)
        {
            throw new NotImplementedException();
        }

        public T this[int index]
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        #endregion

        #region ICollection<T> Implementation

        public void Add(T item)
        {
            _list.Add(item);
            NotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
        }

        public void Clear()
        {
            _list.Clear();
            NotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        public bool Contains(T item)
        {
            return _list.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            _list.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get
            {
                return _list.Count;
            }
        }

        public bool IsReadOnly
        {
            get
            {
                return ((ICollection<T>)_list).IsReadOnly;
            }
        }

        public bool Remove(T item)
        {
            var removed = false;
            var index = _list.FindIndex(i => i.Equals(item));

            if (index >= 0)
            {
                removed = _list.Remove(item);

                if (removed)
                {
                    NotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
                }
            }

            return removed;
        }

        #endregion

        #region IEnumerable<T> Implementation

        public IEnumerator<T> GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        #endregion

        #region IEnumerable Implementation

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        #endregion

		#region Public Methods

		public void BeginUpdate()
		{
			_updateInProgress = true;
		}

		public void EndUpdate()
		{
			if (_updateInProgress)
			{
				_updateInProgress = false;
				NotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
			}
		}

        public void NotifyItemChanged(int index)
        {
            Contract.Assert(index >= 0 && index < _list.Count);

			// TOFIX: find how to use Replace action...
			NotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        public void NotifyItemChanged(T item)
        {
            Contract.Requires(item != null);

			// TOFIX: find how to use Replace action...
			NotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        public void Sort(Comparison<T> comparer)
        {
            _list.Sort(comparer);
			NotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

		#endregion // Public Methods

		#region Fields

		private List<T> _list = new List<T>();
		private bool _updateInProgress;

        #endregion // Fields
    }
}
